iT邦幫忙

2022 iThome 鐵人賽

DAY 26
0
DevOps

自動化測試大作戰系列 第 26

情境題—會員註冊(一)

  • 分享至 

  • xImage
  •  

Medium 清新閱讀版連結

前兩天,我們探討了「網站文章」的情境題;今明兩天,就讓我們探討另一個情境題「會員註冊」吧!

這邊我們同樣假設網站是採前後端分離的設計,因此我們就專注在測試 API 的部分,不過會多一個「註冊驗證信」的部分要實作與做測試驗證。

使用案例

  1. 使用者可填寫註冊資料後送出資料。

  2. 使用者可收到註冊驗證信,且該信件內含有專屬於該使用者的驗證連結。

  3. 使用者點選註冊驗證信中的驗證連結後,將驗證成功,其帳號驗證狀態將轉為已驗證。

    這邊我們使用驗證時間來取代驗證狀態,並以有無驗證時間來判斷是否已驗證

依據以上的使用案例,我們可規畫出以下 API / 功能:

API / 功能規畫

  1. 使用者註冊端點 POST /registers
  2. 使用者驗證端點 GET /users/{id}/validation?token={token}
  3. 註冊驗證信

接著就來實作 API 與註冊驗證信的邏輯吧!

實作

  • database/migrations/2014_10_12_000000_create_users_table.php

    <?php
    
    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;
    
    return new class extends Migration
    {
        /**
         * Run the migrations.
         *
         * @return void
         */
        public function up()
        {
            Schema::create('users', function (Blueprint $table) {
                $table->id();
                $table->string('name');
                $table->string('email')->unique();
                $table->timestamp('email_verified_at')->nullable();
                $table->string('password');
                $table->string('verify_email_token', 128)->nullable();
                $table->rememberToken();
                $table->timestamps();
            });
        }
    
        /**
         * Reverse the migrations.
         *
         * @return void
         */
        public function down()
        {
            Schema::dropIfExists('users');
        }
    };
    
  • app/Models/User.php

    <?php
    
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Foundation\Auth\User as Authenticatable;
    use Illuminate\Notifications\Notifiable;
    use Laravel\Sanctum\HasApiTokens;
    
    class User extends Authenticatable
    {
        use HasApiTokens, HasFactory, Notifiable;
    
        /**
         * The attributes that are mass assignable.
         *
         * @var array<int, string>
         */
        protected $fillable = [
            'name',
            'email',
            'password',
            'email_verified_at',
            'verify_email_token',
        ];
    
        /**
         * The attributes that should be hidden for serialization.
         *
         * @var array<int, string>
         */
        protected $hidden = [
            'password',
            'remember_token',
        ];
    
        /**
         * The attributes that should be cast.
         *
         * @var array<string, string>
         */
        protected $casts = [
            'email_verified_at' => 'datetime',
        ];
    }
    
  • routes/web.php

    <?php
    
    use App\Http\Controllers\UserController;
    use Illuminate\Support\Facades\Route;
    
    Route::post('/register', [UserController::class, 'register'])
        ->name('register');
    
    Route::get('/verify-user-email', [UserController::class, 'verifyUserEmail'])
        ->name('verify-user-email');
    
  • app/Http/Controllers/UserController.php

    <?php
    
    namespace App\Http\Controllers;
    
    use App\Mail\VerifyUserMail;
    use App\Models\User;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Hash;
    use Illuminate\Support\Facades\Mail;
    use Illuminate\Support\Str;
    
    class UserController extends Controller
    {
        public function register(Request $request)
        {
            $request->validate([
                'name' => 'required',
                'email' => 'required',
                'password' => 'required',
            ]);
    
            $user = User::create([
               'name' => $request->input('name'),
               'email' => $request->input('email'),
               'password' => Hash::make($request->input('password')),
               'verify_email_token' => Str::random(128),
            ]);
    
            Mail::to($user->email)
                ->send(new VerifyUserMail($user));
    
            return response()->json('');
        }
    
        public function verifyUserEmail(Request $request)
        {
            $request->validate([
               'token' => 'required',
            ]);
    
            $token = $request->input('token');
    
            $user = User::where('verify_email_token', $token)->first();
    
            if (empty($user)) {
                return response('Failed', 404);
            }
    
            $user->email_verified_at = now();
            $user->save();
    
            return response('Success');
        }
    }
    
  • app/Mail/VerifyUserMail.php

    <?php
    
    namespace App\Mail;
    
    use App\Models\User;
    use Illuminate\Bus\Queueable;
    use Illuminate\Contracts\Queue\ShouldQueue;
    use Illuminate\Mail\Mailable;
    use Illuminate\Queue\SerializesModels;
    
    class VerifyUserMail extends Mailable
    {
        use Queueable, SerializesModels;
    
        private $user;
    
        /**
         * Create a new message instance.
         *
         * @return void
         */
        public function __construct(User $user)
        {
            $this->user = $user;
        }
    
        /**
         * Build the message.
         *
         * @return $this
         */
        public function build()
        {
            $data = [
                'verifyLink' => route('verify-user-email', ['token' => $this->user->verify_email_token]),
            ];
    
            return $this->with($data)
                ->view('view.mail.verify-email');
        }
    }
    
  • resources/views/mail/verify-email.blade.php

    <!DOCTYPE html>
    <html >
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Verify Mail</title>
    </head>
    <body class="antialiased">
    <a href="{{ $verifyLink  }}">Verify Your Email</a>
    </body>
    </html>
    

前置準備

這邊我們要準備的是User 的 Factory 類別:

  1. User Factory

    <?php
    
    namespace Database\Factories;
    
    use Illuminate\Support\Str;
    use Illuminate\Database\Eloquent\Factories\Factory;
    
    class UserFactory extends Factory
    {
        /**
        * Define the model's default state.
        *
        * @return array
        */
        public function definition(): array
        {
            return [
                'name' => $this->faker->name,
                'email' => $this->faker->safeEmail,
                'password' => bcrypt($this->faker->password),
                'remember_token' => Str::random(10),
                'verify_email_token' => Str::random(128),
            ];
        }
    }
    

到這邊為止,我們已經把測試目標準備好了,明天我們就來針對各使用案例來寫測試吧!


上一篇
情境題—文章瀏覽與評論(二)
下一篇
情境題—會員註冊(二)
系列文
自動化測試大作戰31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言